import { CSMesh, KeepSizeObject3D, SketchFrame } from '@amcax/base';
import { sketchEventCenter } from '@app-cad/environments/nextcad/events/SketchEventCenter';
import { ctx2 } from '@app-cad/module';
import {
  BufferAttribute,
  BufferGeometry,
  DoubleSide,
  MeshBasicMaterial,
  Object3D,
  Vector3,
  FontLoader,
  TextGeometry,
  Mesh,
  Quaternion,
} from 'three-legacy';
import gentilisRegular from 'three-legacy/examples/fonts/gentilis_regular.typeface.json';

type DivMeshAttrs = {
  id?: string;
  sketchFrame?: SketchFrame;
  position?: Vector3;
  widthHeight?: {
    width: number;
    height: number;
  };
};

export class DivMesh {
  scene: Object3D; // 场景
  sketchFrame: SketchFrame;
  divMesh: CSMesh;
  position?: Vector3; // 世界坐标
  keepSizeGroup: KeepSizeObject3D;
  widthHeight: { width: number; height: number };
  constructor(attrs: DivMeshAttrs) {
    this.init(attrs);
    this.keepSizeGroup = new KeepSizeObject3D(ctx2.viewer.sceneSetup.camera);
  }
  init(attrs: DivMeshAttrs) {
    this.widthHeight = attrs.widthHeight;
    this.sketchFrame = attrs.sketchFrame;
    this.position = attrs.position;
    const material = new MeshBasicMaterial({
      side: DoubleSide,
      transparent: true,
      opacity: 0.9,
      depthTest: false, // 不进行深度测试
    });
    // 创建几何体（平面）
    const geometry = new BufferGeometry();
    const vertices = this.getGeometryVertices(attrs.widthHeight);
    geometry.setAttribute('position', new BufferAttribute(vertices, 3));
    const mesh = new CSMesh({
      geometry,
      material,
      modelDxid: attrs.id || 'divMesh',
    });
    mesh.setRenderOrder(1000);
    mesh.visible = true;
    geometry.setAttribute('position', new BufferAttribute(vertices, 3));
    this.divMesh = mesh;
    this.setVisible(false);
  }
  setText() {
    const font = new FontLoader().parse(gentilisRegular);
    const textGeometry = new TextGeometry('160.125mm', {
      font: font,
      size: 0.9,
      height: 0.05,
    });
    //添加材质
    const material = new MeshBasicMaterial({
      color: 0x666666,
    });
    const textLabel = new Mesh(textGeometry, material);
    textLabel.position.sub(new Vector3(0.5, 0.2, 0));
    const frame = sketchEventCenter().getSketchInfo().frame;
    const xDir = new Vector3(...frame[2]).negate();
    const zDir = new Vector3(...frame[1]);
    const yDir = new Vector3().crossVectors(xDir, zDir);
    // 创建四元数  从x轴正方向旋转到方向向量 dir0 所需的旋转角度
    const quaternion = new Quaternion().setFromUnitVectors(
      new Vector3(1, 0, 0),
      xDir,
    );
    const quaternion1 = new Quaternion().setFromUnitVectors(
      new Vector3(0, 1, 0),
      yDir,
    );
    const quaternion2 = new Quaternion().setFromUnitVectors(
      new Vector3(0, 0, 1),
      zDir,
    );
    // // 将字体的旋转设为四元数的旋转
    textLabel.setRotationFromQuaternion(quaternion);
    textLabel.setRotationFromQuaternion(quaternion1);
    textLabel.setRotationFromQuaternion(quaternion2);
    return textLabel;
  }
  setColor(color: number) {
    this.divMesh.setColor(color);
  }
  getGeometryVertices({ width, height }) {
    const x = (width - 2) / 30;
    const y = (height - 2) / 32;
    const point1 = this.sketchFrame.toWorld(new Vector3(x, y, 0));
    const point2 = this.sketchFrame.toWorld(new Vector3(x, -y, 0));
    const point3 = this.sketchFrame.toWorld(new Vector3(-x, -y, 0));
    const point4 = this.sketchFrame.toWorld(new Vector3(-x, y, 0));
    const [p1, p2, p3, p4] = [point1, point2, point3, point4].map((v) => {
      return v.sub(this.sketchFrame.toWorld(new Vector3(0, 0, 0)));
    });
    // 定义顶点位置数组
    const vertices = new Float32Array([
      ...p1.toArray(),
      ...p2.toArray(),
      ...p3.toArray(),
      ...p1.toArray(),
      ...p3.toArray(),
      ...p4.toArray(),
    ]);
    return vertices;
  }
  updateVertices({ width, height }) {
    if (height > 0 && width > 0) {
      const vertices = this.getGeometryVertices({ width, height });
      this.divMesh.geometry.setAttribute(
        'position',
        new BufferAttribute(vertices, 3),
      );
    }
  }
  update(attrs: DivMeshAttrs) {
    this.position = attrs.position;
    if (attrs.widthHeight) {
      this.updateVertices(attrs.widthHeight);
    }
    this.setPosition();
  }
  setPosition() {
    this.keepSizeGroup.position.copy(this.position);
  }
  setVisible(visible: boolean) {
    this.divMesh.visible = visible;
  }
  addTo(scene) {
    this.scene = scene;
    scene.add(this.keepSizeGroup);
    this.divMesh.addTo(this.keepSizeGroup);
    this.setPosition();
  }
}
